﻿//此脚本与 /windows_command_line/src/c#/ConsoleHelper.cs 一致 

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace ZXthex
{
    public static class ConsoleHelper
    {
        const string CONSOLE_DLL = "AddConsole";

        [DllImport(CONSOLE_DLL)]
        static extern void before_use_console();
        [DllImport(CONSOLE_DLL)]
        static extern void clean_console_input();
        [DllImport(CONSOLE_DLL)]
        static extern void end_use_console();
        [DllImport(CONSOLE_DLL)]
        static extern void set_ctrl_c_callback(Action callback);

         
        static handleX hdx;

        public static event Action ctrl_c_callback=()=> { };

        /// <summary>
        /// 开启Windows控制台
        /// </summary>
        public static void OpenConsole()
        {
            if (hdx == null)
            {
                before_use_console();
                hdx = new handleX();
                set_ctrl_c_callback(() => { ctrl_c_callback?.Invoke(); CloseConsole(); });
            }
        }

        public static void CleanConsoleInput()
        {
            if (hdx != null)
            {
                clean_console_input();
            }
        }

        /// <summary>
        /// 关闭Windows控制台
        /// </summary>
        public static void CloseConsole()
        {

            if (hdx != null)
            {
                hdx.Dispose();
                hdx = null;
            }
            end_use_console();

        }


        class handleX : IDisposable
        {
            TextWriter oldW;
            TextReader oldR;

            public handleX()
            {
                oldW = Console.Out;
                oldR = Console.In;

                var writer = new StreamWriter(Console.OpenStandardOutput())
                {
                    AutoFlush = true
                };

                Console.SetOut(writer);

                var reader = new StreamReader(Console.OpenStandardInput());
                Console.SetIn(reader);

            }


            ~handleX()
            {
                Dispose();
            }

            bool disposed;

            public void Dispose()
            {
                if (disposed) return;

                Console.In.Close();
                Console.Out.Close();
                Console.SetIn(oldR);
                Console.SetOut(oldW);

                disposed = true;
            }
        }
    }
}